﻿using ASmile.Com;
using ASmile.DBModel;
using ASmile.Extend;
using ASmile.Helpers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Linq;

namespace ASmile.Web
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public abstract class AuthorizeBaseAttribute : Attribute, IAuthorizationFilter
    {
        /// <summary>
        /// 是否验证，如果为false 则取消验证
        /// </summary>
        public bool IsAuth { set; get; } = true;
        /// <summary>
        /// 是否验证角色rule的权限，(登陆后还未获取带role的token时应该是false)
        /// </summary>
        public bool IsAuthRoleUrl { set; get; } = false;

        protected bool CheckFilter(FilterContext context)
        {
            if (!context.IsEffectivePolicy(this)) return false;

            if (!IsAuth) return false;

            return true;
        }

        protected abstract void AuthorizationHandle(AuthorizationFilterContext context);
        
        /// <summary>
        /// 验证登陆用户 ， 成功返回 0 
        /// </summary>
        protected int AuthorizationUserRole(AuthorizationFilterContext context, LoginUser currUser)
        {
            if (!Config.THIS.VerifyRoleUrl) return 0;

            if (!IsAuthRoleUrl) return 0;

            if (currUser.RoleId.IsEmpty())
            {
                //AuthorizationFail(context, 100);
                return 100;
            }

            var rList = DataCacheCom.GetRoleUrlByRoleId(currUser.RoleId);
            if (rList == null || rList.Count == 0)
            {
                //AuthorizationFail(context, 101);
                return 101;
            }

            var path = context.HttpContext.Request.Path.Value;
            var ip = context.HttpContext.GetRemoteIp();
            //Console.WriteLine($"IP:{ip},Path:{path}");
            //匹配到IP返回true,否则未false
            bool MatchIP(Sys_RoleUrl m, int failCode)
            {
                if (!m.IsLimitIP) return true;
                if (m.IPStrs.IsNotEmpty())
                {
                    var ipArrs = m.IPStrs.Split(';', StringSplitOptions.RemoveEmptyEntries);
                    if (ipArrs.Contains(ip))
                    {
                        return true;
                    }
                }
                //AuthorizationFail(context, failCode);
                return false;
            }

            foreach (var item in rList.OrderByDescending(s => s.IsRefuse))
            {
                if (item.MatchMode == 1 && path.StartsWith(item.MatchValue, true, null))
                {
                    if (!MatchIP(item, 102)) return 102;
                    if (item.IsRefuse)
                    {
                        //AuthorizationFail(context, 1021);
                        return 1021;
                    }
                    return 0;
                }
                else if (item.MatchMode == 2 && path.EndsWith(item.MatchValue, true, null))
                {
                    if (!MatchIP(item, 103)) return 103;
                    if (item.IsRefuse)
                    {
                        //AuthorizationFail(context, 1031);
                        return 1031;
                    }
                    return 0;
                }
                else if (item.MatchMode == 3 && path.ContainsLike(item.MatchValue))
                {
                    if (!MatchIP(item, 104)) return 104;
                    if (item.IsRefuse)
                    {
                        //AuthorizationFail(context, 1041);
                        return 1041;
                    }
                    return 0;
                }
                else if (item.MatchMode == 4 && path.StringEquals(item.MatchValue))
                {
                    if (!MatchIP(item, 105)) return 105;
                    if (item.IsRefuse)
                    {
                        //AuthorizationFail(context, 1051);
                        return 105;
                    }
                    return 0;
                }
                else if (item.MatchMode == 5 && RegexHelper.Check(path, item.MatchValue))
                {
                    if (!MatchIP(item, 106)) return 106;
                    if (item.IsRefuse)
                    {
                        //AuthorizationFail(context, 1061);
                        return 1061;
                    }
                    return 0;
                }
            }

            return 199;
            //AuthorizationFail(context, 199);
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            AuthorizationHandle(context);
        }

    }
}
